package com.ly.anno.mybatis;

import lombok.Data;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/11/3
 * Email haijunzhou@hnit.edu.cn
 */
public class SqlSession {

    public <T> T getMapper(Class<T> cls){
        // UserMapper mapper = getMapper(UserMapper.class);
        // JDK动态代理
        // 创建代理对象
        return (T) Proxy.newProxyInstance(cls.getClassLoader(),
                new Class[]{cls},
                // InvocationHandler 方法拦截器, 返回值就是业务方法的返回值
                new InvocationHandler(){
                    @Override
                    public Object invoke(Object proxy, // 动态生成的代理对象
                                         Method method, // 执行的方法
                                         Object[] args  // 执行方法的参数
                    ) throws Throwable {
                        System.out.println("method = " + method);
                        System.out.println("args = " + Arrays.toString(args));
                        System.out.println("method.getReturnType() = " + method.getReturnType());

                        Select select = method.getAnnotation(Select.class);
                        if(select != null){
                            // 这是查询方法
                            String sql = select.value();
                            if(method.getParameterCount() == 1){
                                // 单参数(int ,string, long char), 排除查实体对象
                                sql = sql.replaceAll("#\\{\\w+}", "?");
                                System.out.println("sql = " + sql);
                                System.out.println("参数 = " + Arrays.toString(args));
                                System.out.println("执行语句省略....");
                            } else {
                                // 多参数: 实体对象 , @Param
                            }
                        }
                        return null;
                    }
                });
    }

    public static void main(String[] args) {
        SqlSession sqlSession = new SqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.selectById(100);
        mapper.selectLikeName("张三");
    }

}

@Retention(RetentionPolicy.RUNTIME)
@interface Insert{ String value(); }
@Retention(RetentionPolicy.RUNTIME)
@interface Select{ String value(); }
@Retention(RetentionPolicy.RUNTIME)
@interface Update{ String value(); }
@Retention(RetentionPolicy.RUNTIME)
@interface Delete{ String value(); }
@Retention(RetentionPolicy.RUNTIME)
@interface Param{ String value(); }

// 实体类
@Data
class User{
    Integer id;
    String username;
    String password;
}
// Mapper 接口
interface UserMapper {
    @Insert("insert into test_user (username, password) values(#{usr},#{pwd})")
    void insert(@Param("usr") String username, @Param("pwd") String password);
    @Update("update test_user set username = #{username}, password = #{password} where id = #{id}")
    int update(User user);
    @Select("select * from test_user where id = #{id}")
    User selectById(int id);
    @Select("select * from test_user where username like #{uname}")
    List< User > selectLikeName(String username);
}
// 提示: 如何获取方法返回值泛型类型? 请参考以下代码
class Demo {
    public static Class getGenericReturnType(Class cls, String methodName,Class...classes){
        try{
            // 获取方法对象
            Method declaredMethod = cls.getDeclaredMethod(methodName, classes);
            // 获取返回值类型 Type (注意:Type不是Class)
            Type type = declaredMethod.getGenericReturnType();
            // 转型 ParameterizedType
            ParameterizedType pType=(ParameterizedType)type;
            // 获取泛型数组中的第一个泛型类型
            Class ret = (Class) pType.getActualTypeArguments()[0];
            return ret;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}